#ifndef __M_UTIL_H__
#define __M_UTIL_H__

#include <iostream>
#include <mysql/mysql.h>
#include <string>
#include <sstream>
#include <fstream>
#include <memory>
#include <jsoncpp/json/json.h>
#include <vector>
#include "logger.hpp"
#include <mutex>
#include <assert.h>

class mysql_util {
    public:
        static MYSQL *mysql_creat(const std::string &host,
            const std::string &username,
            const std::string &password,
            const std::string &dbname,
            uint16_t port = 3306
        ){
                    //1.初始化mysql句柄
            MYSQL *mysql = mysql_init(NULL);
            if(mysql == NULL)
            {
                ELOG("mysql初始化失败");
                return NULL;
            }

            //2.连接服务器
            if(mysql_real_connect(mysql,host.c_str(),username.c_str(),password.c_str(),dbname.c_str(),port,NULL,0) == 0)
            {
                ELOG("连接失败:%s\n",mysql_error(mysql));
                mysql_close(mysql);
                return NULL;
            }
            
            //3.设置客户端字符集
            if(mysql_set_character_set(mysql,"utf8") != 0) {
                ELOG("客户端链接失败:%s\n",mysql_error(mysql));
                mysql_close(mysql);
                return NULL;

        }
            return mysql;

        }
        
        static bool mysql_exec(MYSQL *mysql,const std::string &sql){
            int ret = mysql_query(mysql,sql.c_str());
                if(ret != 0)
                {
                    ELOG("%s",sql);
                    ELOG("语句失败:%s",mysql_error(mysql));
                    //mysql_close(mysql);
                    return false;
                }
                return true;
                
        }

        static void mysql_destory(MYSQL *mysql){
                if (mysql != NULL){
                    mysql_close(mysql);
                }

            return;
        }


};


class json_util{
    public:
        static bool serialize(const Json::Value &root,std::string &str)
        {
                //2.实例化一个StreamWriterBuilder工厂类对象
                Json::StreamWriterBuilder swb;

                //3.通过StreamWriterBuilder工厂类对象生产一个StreamWriter对象
                std::unique_ptr<Json::StreamWriter>sw(swb.newStreamWriter());

                //4.使用StreamWriter对象，对Json:Value中存储的数据进行序列化
                std::stringstream ss;
                int ret = sw->write(root,&ss);
                if(ret != 0) {
                    ELOG("Json 出错");
                    return false;
                }

                str = ss.str();
                return true;
        }

        static bool unserialize(const std::string &str,Json::Value &root)
        {
                //1.实例化一个CharReaderBuilder工厂类对象
                Json::CharReaderBuilder crb;

                //2.使用CharReaderBuilder工厂类生成一个CharReader对象
                std::unique_ptr<Json::CharReader>cr(crb.newCharReader());

                //3.定义一个Json::Value对象存储解析后的数据
                //存储错误信息
                std::string err;

                //4.使用CharReader对象进行json格式字符串str的反序列化
                bool ret = cr->parse(str.c_str(),str.c_str() + str.size(),&root,&err);
                if(ret == false) 
                {
                    ELOG("Json反序列化失败: %s ",err.c_str());
                    return false;
                }
                return true;
        }


};

class string_util{
    public:
        static int split(const std::string &src,const std::string &sep,std::vector<std::string> &res) {
            // 123,456,,,789
            size_t pos,idx = 0;
            
            while(idx < src.size())
            {
            pos = src.find(sep,idx);
            //没有找到
            if(pos == std::string::npos) {
                res.push_back(src.substr(idx));
                break;
            }

            if(pos == idx)
            {
                idx += sep.size();
                continue;
            }

            res.push_back(src.substr(idx,pos - idx));
            idx = pos + sep.size();

            }
            return res.size();
        }
};


class file_util {
    public:
        static bool read(const std::string &filename,std::string &body)
        {
            //打开文件
            std::ifstream ifs(filename,std::ios::binary);
            if(ifs.is_open() == false)
            {
                ELOG("%s 文件打开失败",filename.c_str());
                return false;
            }
            //获取文件大小
            size_t fsize = 0;
            ifs.seekg(0,std::ios::end);
            fsize = ifs.tellg();
            ifs.seekg(0,std::ios::beg);
            body.resize(fsize);
            //将文件所有数据读取出来
            ifs.read(&body[0],fsize); 
            if(ifs.good() == false)
            {
                ELOG("读取 %s 文件失败",filename.c_str());
                ifs.close();
                return false;
            }

            //关闭文件
            ifs.close();
            return true;


        }




};














#endif